import {computeNormals} from "./primitiveUtils";
import {VertexData} from "../core/vertexData";

export function sphere(
    radius: number,
    segments_width: number = 8,
    segments_height: number = 6
):VertexData {

    let data: {
        positions: number[],
        normals: number[],
        texCoords: number[],
        indices: number[]
    } = {
        positions: [],
        normals: [],
        texCoords: [],
        indices: []
    };


    let gridX = segments_width,
        gridY = segments_height;

    let i, j;
    let iHor = Math.max( 3, gridX );
    let iVer = Math.max( 2, gridY );
    let aVtc = [];

    for ( j = 0; j < ( iVer + 1 ) ; j++ ) {

        let fRad1 = j / iVer;
        let fZ = radius * Math.cos( fRad1 * Math.PI );
        let fRds = radius * Math.sin( fRad1 * Math.PI );
        let aRow = [];
        let oVtx = 0;

        for ( i = 0; i < iHor; i++ ) {

            let fRad2 = 2 * i / iHor;
            let fX = fRds * Math.sin( fRad2 * Math.PI );
            let fY = fRds * Math.cos( fRad2 * Math.PI );

            if ( !( ( j == 0 || j == iVer ) && i > 0 ) ) {
                oVtx = data.positions.push( fY, fZ, fX ) / 3 - 1;
            }

            aRow.push( oVtx );

        }

        aVtc.push( aRow );

    }

    let iVerNum = aVtc.length;

    for ( j = 0; j < iVerNum; j++ ) {

        let iHorNum = aVtc[ j ].length;

        if ( j > 0 ) {

            for ( i = 0; i < iHorNum; i++ ) {

                let bEnd = i == ( iHorNum - 1 );
                let aP1 = aVtc[ j ][ bEnd ? 0 : i + 1 ];
                let aP2 = aVtc[ j ][ ( bEnd ? iHorNum - 1 : i ) ];
                let aP3 = aVtc[ j - 1 ][ ( bEnd ? iHorNum - 1 : i ) ];
                let aP4 = aVtc[ j - 1 ][ bEnd ? 0 : i + 1 ];

                let fJ0 = j / ( iVerNum - 1 );
                let fJ1 = ( j - 1 ) / ( iVerNum - 1 );
                let fI0 = ( i + 1 ) / iHorNum;
                let fI1 = i / iHorNum;

                let aP1uv = [ 1 - fI0, fJ0 ];
                let aP2uv = [ 1 - fI1, fJ0 ];
                let aP3uv = [ 1 - fI1, fJ1 ];
                let aP4uv = [ 1 - fI0, fJ1 ];

                if ( j < ( aVtc.length - 1 ) ) {
                    data.indices.push(aP1, aP2, aP3 );
                    data.texCoords.push( ...aP1uv, ...aP2uv, ...aP3uv);
                }

                if ( j > 1 ) {
                    data.indices.push(aP1, aP3, aP4);
                    data.texCoords.push( ...aP1uv, ...aP3uv, ...aP4uv );
                }

            }
        }
    }

    computeNormals(data);

    return new VertexData(data);
}
